package com.atguigu.shiro.config;

import com.atguigu.shiro.realm.MyRealm;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.io.InputStream;

/**
 * @Author: wh
 * @Date: 2025/8/3 17:30
 */
@Configuration
public class ShiroConfig {
    @Autowired
    private MyRealm myRealm;

    // 配置SecurityManager
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() {
        // 1.创建DefaultWebSecurityManager对象
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        // 2.创建加密对象，设置相关属性
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        // 2.1 采用md5加密
        matcher.setHashAlgorithmName("md5");
        // 2.2 迭代次数
        matcher.setHashIterations(3);
        // 3.将加密对象存储到myRealm中
        myRealm.setCredentialsMatcher(matcher);
        // 4.将myRealm存入DefaultWebSecurityManager对象中
        defaultWebSecurityManager.setRealm(myRealm);
        // 4.5 设置RememberMe
        defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
        // 4.6设置缓存管理器(这里设置了缓存管理器之后，进行省份验证时直接从缓存中拿取数据，不在从数据库中进行查询)
        defaultWebSecurityManager.setCacheManager(getEhCacheManager());

        // 5.返回
        return defaultWebSecurityManager;
    }

    //cookie属性设置
    public SimpleCookie rememberMeCookie(){
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        //设置跨域
        //cookie.setDomain(domain);
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30*24*60*60);
        return cookie;
    }
    //创建Shiro的cookie管理对象
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());

        cookieRememberMeManager.setCipherKey("1234567890987654".getBytes());
        return cookieRememberMeManager;
    }

    // 缓存管理器
    public EhCacheManager getEhCacheManager(){
        EhCacheManager ehCacheManager = new EhCacheManager();
        InputStream is = null;
        try {
            is = ResourceUtils.getInputStreamForPath( "classpath:ehcache/ehcache-shiro.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        CacheManager cacheManager = new CacheManager(is);
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }

    //配置 Shiro 内置过滤器拦截范围
    @Bean
    public DefaultShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        //设置不认证可以访问的资源
        // 参数二表示过滤器别名：anon 表示该路径可以被匿名访问，即不需要认证（登录）就可以访问
        //  anon 表示该路径可以被匿名访问，即不需要认证（登录）就可以访问
        //  authc：表示需要认证才能访问（你配置中的 /** 使用了这个）
        //  roles：需要特定角色
        //  perms：需要特定权限
        //  logout：退出登录
        definition.addPathDefinition("/myController/userLogin", "anon");
        definition.addPathDefinition("/myController/login", "anon");
        //配置登出过滤器，注意这里的logout必须要卸载/**过滤器的前面，否则会无法生效
        definition.addPathDefinition("/logout","logout");
        //设置需要进行登录认证的拦截范围
        definition.addPathDefinition("/**", "authc");
        //添加存在用户的过滤器（rememberMe）,user 是一个内置的过滤器, 表示用户必须是被认证（登录）的 或 通过 "Remember Me" 功能记住登录状态的用户才能访问该资源。
        definition.addPathDefinition("/**","user");

        return definition;
    }

    /*
    * RememberMe整体流程：
    * 1、用户登录时勾选 "Remember Me"。
    * 2、Shiro 调用 rememberMeManager，将用户身份信息加密后存入 rememberMe Cookie。
    * 3、浏览器关闭后再次访问时，Shiro 自动从 Cookie 解密并恢复登录状态（无需重新输入账号密码）。
    * */

}
